package com.taobao.shopcart.jobhandler;


import com.taobao.shopcart.mapper.OrderProcessMapper;
import com.taobao.shopcart.mapper.OrdersMapper;
import com.taobao.shopcart.model.po.OrderProcess;
import com.taobao.shopcart.model.po.Orders;
import com.taobao.shopcart.service.ProcessService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * 任务处理类
 */

@Slf4j
@Component
public class OrderTask {

    @Autowired
    private ProcessService processService;
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrderProcessMapper orderProcessMapper;

    /**
     * 订单处理
     */
    @XxlJob("orderJobHandler")
    @Transactional
    public void orderJobHandler() throws Exception {

        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex();//执行器的序号，从0开始
        int shardTotal = XxlJobHelper.getShardTotal();//执行器总数

        //确定cpu的核心数
        int processors = Runtime.getRuntime().availableProcessors();
        List<OrderProcess> processList = processService.getProcessList(shardIndex, shardTotal, processors);
        //任务数量
        int size = processList.size();
        log.debug("取到未支付订单数:" + size);
        if (size <= 0) {
            return;
        }
        //创建一个线程池
        ExecutorService executorService = Executors.newFixedThreadPool(size);
        //使用的计数器
        CountDownLatch countDownLatch = new CountDownLatch(size);
        processList.forEach(process -> {
            //将任务加入线程池
            executorService.execute(() -> {
                //任务id
                long taskId = process.getId();
                try {
                    //开启任务
                    boolean b = processService.startTask(taskId);
                    if (!b) {
                        log.debug("抢占任务失败,任务id:{}", taskId);
                        return;
                    }
                    //执行任务
                    System.out.println("线程池执行任务");
                    Orders order = ordersMapper.selectByOrderId(process.getOrderId());

                    switch (process.getTypes()) {
                        case 1: // 提示用户支付
                            if (Duration.between(order.getCreatedAt(), LocalDateTime.now()).compareTo(Duration.ofMinutes(10)) > 0) { // 未支付 且超过十分钟
                                System.err.println("发送短信提示用户支付" + order.getOrderId());
                                // todo: 发送短信
                                orderProcessMapper.updateTypeById(process.getId(), 3);
                            }else {
                                // 没超过10分钟
                                orderProcessMapper.updateTypeById(process.getId(), 1);
                            }
                            break;
                        case 2: // 处理超时订单
                            order.setStatus(4);
                            order.setUpdateAt(LocalDateTime.now());
                            int i = this.ordersMapper.updateByOrderId(order.getOrderId(), order.getStatus(), order.getUpdateAt());
                            if (i != 1) {
                                log.error("订单更新失败");
                                return;
                            }
                            //保存任务处理成功的结果
                            this.processService.saveProcessFinishStatus(taskId, 2, "订单超时取消");
                            break;
                        case 3: // 等待超时
                            orderProcessMapper.updateTypeById(process.getId(), 1);
                            break;
                    }
                } catch (Exception e) {
                    log.error("订单处理失败", e);
                    processService.saveProcessFinishStatus(taskId, 3, e.getMessage());
                } finally {
                    //计算器减去1
                    countDownLatch.countDown();
                }
            });
        });

        //阻塞,指定最大限制的等待时间，阻塞最多等待一定的时间后就解除阻塞
        countDownLatch.await(30, TimeUnit.MINUTES);
    }

    /**
     * 添加任务  应该放在创建订单里执行
     */
    @XxlJob("addProcess")
    public void addProcess() {
        List<Orders> orders = ordersMapper.selectOrderStatus();
        OrderProcess orderProcess = new OrderProcess();
        orders.forEach(order -> {
            if (Duration.between(order.getCreatedAt(), LocalDateTime.now()).compareTo(Duration.ofMinutes(15)) > 0) {
                //超过15分钟
                orderProcess.setTypes(2); // 2 超时未支付
            } else { // 0 待支付
                orderProcess.setTypes(1); // 1 支付类型
            }
            orderProcess.setStatus(1); // 1 待处理
            orderProcess.setUpdateTime(LocalDateTime.now());
            orderProcess.setFailCount(0);
            orderProcess.setOrderId(order.getOrderId());
            if (orderProcessMapper.selectByOrderId(order.getOrderId()) == null) {
                orderProcessMapper.insert(orderProcess);
            }
        });
    }

}
